//========================================================================
// FILENAME : adc.c
// CREATED : 23-02-2009
// AUTHOR : Jesper Aagaard Vuholm
// DESCR. : This file contains the implementation of our AD-conversions.
//
//------------------------------------------------------------------------
//
// REV. DATE/AUTHOR CHANGE DESCRIPTION
// 1.00 24-02-2009/Jesper prototype functions created.
// 1.01 25-02-2009/Jesper free running mode implemented.
// 1.02 26-02-2009/Jesper code have been tested, via 6 pot-meters.
// 1.03 27-02-2009/Jesper fast ADMUX channel selector implemented.
//========================================================================
#include "adc.h"

#include <avr/io.h>
#include <avr/interrupt.h>

#define sbi(port,pin)    port |= 1<<pin    //set bit
#define cbi(port,pin)    port &= ~(1<<pin) //clear bit

//=============================================================
// METHOD : void ADC_init()
// DESCR. : Enables ADC by setting the ADEN bit in the ADCSRA
//          register.
//=============================================================
void ADC_init()
{
	sbi(ADCSRA, ADEN);
}

//=============================================================
// METHOD : void ADC_start()
// DESCR. : Starts the AD-conversion by setting the ADSC bit
//          in the ADCSRA register.
//=============================================================
void ADC_start()
{
	sbi(ADCSRA, ADSC);
}

//=============================================================
// METHOD : void ADC_startScan()
// DESCR. : Enables the ISR by setting the ADIE bit
//          in the ADCSRA register.
//=============================================================
void ADC_startScan()
{
	sbi(ADCSRA, ADIE);
	ADC_start();
}

//=============================================================
// METHOD : void ADC_stop()
// DESCR. : Stops the AD-conversion by clearing the ADSC bit
//          in the ADCSRA register.
//=============================================================
void ADC_stop()
{
	cbi(ADCSRA, ADIE); // Disable ISR
}


//=============================================================
// METHOD : ISR(ADC_vect)
// DESCR. : Our ADC interrupt service routine(ISR), this routine
//          stores the current value in the correct place. The
//          indexer which controls the ADMUX channel is then
//          incremented, and a new conversion is started before
//          exiting the routine. This interrupt routine is fired
//          when a AD conversion is finished.
//=============================================================
ISR(ADC_vect)
{
	static unsigned char priority_index = 0; //Auto-incrementation will make it flip, saves us time in the ISR.
	ADC_raw_values[priority_list[priority_index]]= ADC; // Store current AD conversion result
	priority_index++;
	ADC_setPin(priority_list[priority_index]);
	ADC_start();
}


//=============================================================
// METHOD : void ADC_setPin (unsigned char pin)
// DESCR. : Selects the correct channel for the next
//          AD-conversion. Since the only bits we use in the
//          ADMUX register is MUX4:0 we can just set ADMUX = pin.
//=============================================================
void ADC_setPin (unsigned char pin)
{
	ADMUX = pin;
	// PWM the data to the LEDS, so that the light intenseness
	// will reveal our "visit-freq." pattern.
	PORTB = 255;
	cbi(PORTB,pin);
}
